#pragma once

#include <unordered_map>
#include <set>
#include <typeindex>
#include "Event.h"
#include "EventHandler.h"
#include "Subscriber.h"


class EventBus final
{
public:
    EventBus() = default;
    ~EventBus() = default;

template<typename T>
    void subscribe(EventHandler&& handler)
    {
        auto typeIndex = std::type_index(typeid(T));
        if(_handlers.find(typeIndex) == _handlers.end())
        {
            _handlers[typeIndex] = std::multiset<EventHandler>();
        }
        _handlers[typeIndex].insert(std::move(handler));
    }

template<typename T>
    void publish(Event& event)
    {
        auto typeIndex = std::type_index(typeid(T));
        if(!_handlers.count(typeIndex)) return;
        auto& handlers = _handlers[typeIndex];
        for(auto it = handlers.begin(); it!= handlers.end();)
        {
            auto& handler = *it;
            if(!handler.is_valid())
            {
                it = handlers.erase(it);
                continue;
            }
            handler(event);
            ++it;
            if(event.is_canceled()) break;
        }
    }
private:
    std::unordered_map<std::type_index, std::multiset<EventHandler>> _handlers;
};